package com.xp.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xp.dto.LogicFlowData;
import com.xp.dto.LiteFlowConvertResult;
import com.xp.dto.NodeDefinitionDTO;
import com.xp.service.FlowDataConvertService;
import com.xp.service.NodeDefinitionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程数据转换服务实现类
 *
 * @author xp
 * @since 2025-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FlowDataConvertServiceImpl implements FlowDataConvertService {

    private final ObjectMapper objectMapper;
    private final NodeDefinitionService nodeDefinitionService;

    /**
     * 将LogicFlow数据转换为LiteFlow EL表达式
     */
    @Override
    public LiteFlowConvertResult convertToLiteFlow(LogicFlowData logicFlowData) {
        long startTime = System.currentTimeMillis();

        try {
            // 验证输入数据
            if (!validateLogicFlowData(logicFlowData)) {
                return LiteFlowConvertResult.failure("LogicFlow数据格式不正确");
            }

            List<LogicFlowData.Node> nodes = logicFlowData.getNodes();
            List<LogicFlowData.Edge> edges = logicFlowData.getEdges();

            // 构建节点映射
            Map<String, LogicFlowData.Node> nodeMap = nodes.stream()
                    .collect(Collectors.toMap(LogicFlowData.Node::getId, node -> node));

            // 构建连接关系图
            Map<String, List<String>> adjacencyMap = buildAdjacencyMap(edges);

            // 查找开始节点
            LogicFlowData.Node startNode = findStartNode(nodes);
            if (startNode == null) {
                return LiteFlowConvertResult.failure("未找到开始节点");
            }

            // 生成节点组件映射
            Map<String, LiteFlowConvertResult.NodeComponentInfo> nodeComponentMapping =
                    generateNodeComponentMappingInternal(nodes);

            // 生成EL表达式
            String elExpression = generateElExpression(startNode, nodeMap, adjacencyMap, new HashSet<>());

            // 创建转换结果
            LiteFlowConvertResult result = LiteFlowConvertResult.success(elExpression, nodeComponentMapping);

            // 设置统计信息
            LiteFlowConvertResult.ConvertStatistics statistics = new LiteFlowConvertResult.ConvertStatistics();
            statistics.setTotalNodes(nodes.size());
            statistics.setTotalEdges(edges.size());
            statistics.setConvertedNodes(nodeComponentMapping.size());
            statistics.setSkippedNodes(nodes.size() - nodeComponentMapping.size());
            statistics.setConvertTime(System.currentTimeMillis() - startTime);
            result.setStatistics(statistics);

            log.info("LogicFlow数据转换成功，生成EL表达式: {}", elExpression);
            return result;

        } catch (Exception e) {
            log.error("LogicFlow数据转换失败", e);
            return LiteFlowConvertResult.failure("转换失败: " + e.getMessage());
        }
    }

    /**
     * 将LogicFlow JSON字符串转换为LiteFlow EL表达式
     */
    @Override
    public LiteFlowConvertResult convertToLiteFlow(String logicFlowJson) {
        try {
            if (!StringUtils.hasText(logicFlowJson)) {
                return LiteFlowConvertResult.failure("LogicFlow JSON数据不能为空");
            }

            log.info("开始转换LogicFlow数据，原始JSON: {}", logicFlowJson);

            // 直接解析为LogicFlowData对象
            LogicFlowData logicFlowData = objectMapper.readValue(logicFlowJson, LogicFlowData.class);
            return convertToLiteFlow(logicFlowData);

        } catch (Exception e) {
            log.error("解析LogicFlow JSON数据失败: {}", e.getMessage(), e);
            return LiteFlowConvertResult.failure("解析LogicFlow数据失败: " + e.getMessage());
        }
    }

    /**
     * 验证LogicFlow数据格式
     */
    @Override
    public boolean validateLogicFlowData(LogicFlowData logicFlowData) {
        if (logicFlowData == null) {
            log.error("LogicFlow数据验证失败: logicFlowData为null");
            return false;
        }

        if (logicFlowData.getNodes() == null) {
            log.error("LogicFlow数据验证失败: nodes为null");
            return false;
        }

        if (logicFlowData.getNodes().isEmpty()) {
            log.error("LogicFlow数据验证失败: nodes为空列表");
            return false;
        }

        // 验证节点数据完整性
        for (LogicFlowData.Node node : logicFlowData.getNodes()) {
            if (!StringUtils.hasText(node.getId())) {
                log.error("LogicFlow数据验证失败: 节点ID为空, node: {}", node);
                return false;
            }
            if (!StringUtils.hasText(node.getType())) {
                log.error("LogicFlow数据验证失败: 节点类型为空, nodeId: {}", node.getId());
                return false;
            }
        }

        log.info("LogicFlow数据验证成功, 节点数量: {}", logicFlowData.getNodes().size());
        return true;
    }

    /**
     * 验证LiteFlow EL表达式
     */
    @Override
    public boolean validateLiteFlowExpression(String elExpression) {
        if (!StringUtils.hasText(elExpression)) {
            return false;
        }

        // 基本的EL表达式格式验证
        String trimmed = elExpression.trim();
        return trimmed.contains("(") && trimmed.contains(")") && trimmed.endsWith(";");
    }

    /**
     * 生成节点组件映射
     */
    @Override
    public String generateNodeComponentMapping(LogicFlowData logicFlowData) {
        try {
            Map<String, LiteFlowConvertResult.NodeComponentInfo> mapping =
                    generateNodeComponentMappingInternal(logicFlowData.getNodes());
            return objectMapper.writeValueAsString(mapping);
        } catch (Exception e) {
            log.error("生成节点组件映射失败", e);
            return "{}";
        }
    }

    /**
     * 构建邻接表
     */
    private Map<String, List<String>> buildAdjacencyMap(List<LogicFlowData.Edge> edges) {
        Map<String, List<String>> adjacencyMap = new HashMap<>();

        for (LogicFlowData.Edge edge : edges) {
            String sourceId = edge.getSourceNodeId();
            String targetId = edge.getTargetNodeId();

            adjacencyMap.computeIfAbsent(sourceId, k -> new ArrayList<>()).add(targetId);
        }

        return adjacencyMap;
    }

    /**
     * 查找开始节点
     */
    /**
     * 查找开始节点
     * 通过节点属性中的nodeType来识别开始节点
     */
    private LogicFlowData.Node findStartNode(List<LogicFlowData.Node> nodes) {
        return nodes.stream()
                .filter(node -> {
                    // 首先检查节点属性中的nodeType
                    if (node.getProperties() != null && node.getProperties().containsKey("nodeType")) {
                        String nodeType = String.valueOf(node.getProperties().get("nodeType"));
                        return "start".equals(nodeType.toLowerCase());
                    }
                    // 备用方案：检查type字段是否包含start相关的值
                    String type = node.getType();
                    return type != null && (type.toLowerCase().contains("start") || "start".equals(type));
                })
                .findFirst()
                .orElse(null);
    }

    /**
     * 生成EL表达式（递归方法）
     */
    private String generateElExpression(LogicFlowData.Node currentNode,
                                       Map<String, LogicFlowData.Node> nodeMap,
                                       Map<String, List<String>> adjacencyMap,
                                       Set<String> visited) {

        if (visited.contains(currentNode.getId())) {
            return ""; // 避免循环
        }
        visited.add(currentNode.getId());

        String nodeType = currentNode.getType();
        List<String> nextNodeIds = adjacencyMap.getOrDefault(currentNode.getId(), new ArrayList<>());

        // 处理结束节点 - 结束节点不生成组件
        if ("end".equals(nodeType.toLowerCase())) {
            return "";
        }

        // 处理开始节点 - 开始节点不生成组件，直接处理后续节点
        if ("start".equals(nodeType.toLowerCase())) {
            if (nextNodeIds.size() == 1) {
                LogicFlowData.Node nextNode = nodeMap.get(nextNodeIds.get(0));
                return generateElExpression(nextNode, nodeMap, adjacencyMap, visited);
            } else if (nextNodeIds.size() > 1) {
                // 开始节点有多个后续节点，按顺序执行
                return generateSequentialExpression(nextNodeIds, nodeMap, adjacencyMap, visited);
            }
            return "";
        }

        // 处理条件节点 - 使用SWITCH语法
        if ("condition".equals(nodeType.toLowerCase()) || "diamond".equals(nodeType.toLowerCase())) {
            if (nextNodeIds.size() >= 2) {
                String componentName = getComponentName(currentNode);
                List<String> branches = new ArrayList<>();

                for (String nextNodeId : nextNodeIds) {
                    LogicFlowData.Node nextNode = nodeMap.get(nextNodeId);
                    String branch = generateElExpression(nextNode, nodeMap, adjacencyMap, new HashSet<>(visited));
                    if (StringUtils.hasText(branch)) {
                        branches.add(branch);
                    }
                }

                if (branches.size() == 2) {
                    return String.format("SWITCH(%s).to(%s, %s)", componentName, branches.get(0), branches.get(1));
                } else if (branches.size() > 2) {
                    return String.format("SWITCH(%s).to(%s)", componentName, String.join(", ", branches));
                }
            }
        }

        // 处理并行节点 - 使用WHEN语法
        if ("parallel".equals(nodeType.toLowerCase())) {
            if (nextNodeIds.size() > 1) {
                List<String> parallelBranches = new ArrayList<>();
                for (String nextNodeId : nextNodeIds) {
                    LogicFlowData.Node nextNode = nodeMap.get(nextNodeId);
                    String branch = generateElExpression(nextNode, nodeMap, adjacencyMap, new HashSet<>(visited));
                    if (StringUtils.hasText(branch)) {
                        parallelBranches.add(branch);
                    }
                }
                if (!parallelBranches.isEmpty()) {
                    return String.format("WHEN(%s)", String.join(", ", parallelBranches));
                }
            }
        }

        // 处理普通节点 - 收集连续的普通节点，生成平铺的THEN结构
        String componentName = getComponentName(currentNode);
        if (StringUtils.hasText(componentName)) {
            if (nextNodeIds.size() == 1) {
                LogicFlowData.Node nextNode = nodeMap.get(nextNodeIds.get(0));

                // 收集连续的普通节点
                List<String> sequentialComponents = new ArrayList<>();
                sequentialComponents.add(componentName);

                LogicFlowData.Node currentNextNode = nextNode;
                Set<String> tempVisited = new HashSet<>(visited);

                // 遍历连续的普通节点（非条件、非并行、非结束节点）
                while (currentNextNode != null &&
                       !tempVisited.contains(currentNextNode.getId()) &&
                       !"condition".equals(currentNextNode.getType()) &&
                       !"diamond".equals(currentNextNode.getType()) &&
                       !"parallel".equals(currentNextNode.getType()) &&
                       !"end".equals(currentNextNode.getType())) {

                    tempVisited.add(currentNextNode.getId());
                    String nextComponentName = getComponentName(currentNextNode);
                    if (StringUtils.hasText(nextComponentName)) {
                        sequentialComponents.add(nextComponentName);
                    }

                    List<String> nextNodeNextIds = adjacencyMap.getOrDefault(currentNextNode.getId(), new ArrayList<>());
                    if (nextNodeNextIds.size() == 1) {
                        currentNextNode = nodeMap.get(nextNodeNextIds.get(0));
                    } else {
                        break; // 多个后续节点或没有后续节点，停止收集
                    }
                }

                // 更新visited集合
                visited.addAll(tempVisited);

                // 处理剩余的节点
                String remainingExpression = "";
                if (currentNextNode != null && !visited.contains(currentNextNode.getId())) {
                    remainingExpression = generateElExpression(currentNextNode, nodeMap, adjacencyMap, visited);
                }

                // 生成表达式
                if (sequentialComponents.size() == 1 && !StringUtils.hasText(remainingExpression)) {
                    return componentName;
                } else if (sequentialComponents.size() > 1 && !StringUtils.hasText(remainingExpression)) {
                    return String.format("THEN(%s)", String.join(", ", sequentialComponents));
                } else if (sequentialComponents.size() == 1 && StringUtils.hasText(remainingExpression)) {
                    return String.format("THEN(%s, %s)", componentName, remainingExpression);
                } else {
                    return String.format("THEN(%s, %s)", String.join(", ", sequentialComponents), remainingExpression);
                }
            } else if (nextNodeIds.size() > 1) {
                // 多个后续节点，顺序执行
                String sequentialExpression = generateSequentialExpression(nextNodeIds, nodeMap, adjacencyMap, visited);
                if (StringUtils.hasText(sequentialExpression)) {
                    return String.format("THEN(%s, %s)", componentName, sequentialExpression);
                } else {
                    return componentName;
                }
            } else {
                return componentName;
            }
        }

        return "";
    }

    /**
     * 生成顺序执行表达式
     */
    private String generateSequentialExpression(List<String> nodeIds,
                                              Map<String, LogicFlowData.Node> nodeMap,
                                              Map<String, List<String>> adjacencyMap,
                                              Set<String> visited) {
        List<String> expressions = new ArrayList<>();

        for (String nodeId : nodeIds) {
            LogicFlowData.Node node = nodeMap.get(nodeId);
            if (node != null) {
                String expression = generateElExpression(node, nodeMap, adjacencyMap, new HashSet<>(visited));
                if (StringUtils.hasText(expression)) {
                    expressions.add(expression);
                }
            }
        }

        if (expressions.size() == 1) {
            return expressions.get(0);
        } else if (expressions.size() > 1) {
            return String.format("THEN(%s)", String.join(", ", expressions));
        }

        return "";
    }

    /**
     * 获取组件名称
     * 直接使用节点的type字段作为nodeCode，因为前端传递的type字段就是nodeCode
     */
    private String getComponentName(LogicFlowData.Node node) {
        String nodeType = node.getType();
        String nodeId = node.getId().replaceAll("-", "");

        // 通过节点属性中的nodeType跳过开始和结束节点
        if (node.getProperties() != null && node.getProperties().containsKey("nodeType")) {
            String actualNodeType = String.valueOf(node.getProperties().get("nodeType"));
            if ("START".equals(actualNodeType) || "END".equals(actualNodeType)) {
                return "";
            }
        }

        // 备用方案：检查type字段
        if ("start".equals(nodeType) || "end".equals(nodeType) ||
            (nodeType != null && (nodeType.toLowerCase().contains("start") || nodeType.toLowerCase().contains("end")))) {
            return "";
        }

        // 直接使用节点的type字段作为nodeCode
        // 因为前端传递的type字段实际上就是nodeCode
        String nodeCode = nodeType;

        if (StringUtils.hasText(nodeCode)) {
            // 使用tag语法：nodeCode.tag("节点ID")
            // 这样同一类型的组件可以通过tag区分不同的实例
            String tagValue = nodeId.substring(0, Math.min(8, nodeId.length()));
            log.debug("使用nodeCode: {}, tag: {}", nodeCode, tagValue);
            return nodeCode + ".tag(\"" + tagValue + "\")";
        }

        // 如果nodeCode为空，使用原有的映射逻辑作为备用方案
        log.warn("nodeCode为空，使用默认映射，节点类型: {}", nodeType);
        String componentName = mapNodeTypeToComponentName(nodeType);
        String tagValue = nodeId.substring(0, Math.min(8, nodeId.length()));
        return componentName + ".tag(\"" + tagValue + "\")";
    }

    /**
     * 将节点类型映射到实际的组件名称
     */
    private String mapNodeTypeToComponentName(String nodeType) {
        switch (nodeType.toLowerCase()) {
            case "script":
                return "SCRIPT_EXECUTE"; // 使用脚本执行组件
            case "groovy":
                return "SCRIPT_EXECUTE"; // 使用脚本执行组件
            case "http":
                return "HTTP_REQUEST"; // 使用HTTP请求组件
            case "database":
                return "database";
            case "email":
                return "email";
            case "condition":
                return "CONDITION"; // 使用条件判断组件
            case "loop":
                return "loop";
            case "transform":
                return "DATA_TRANSFORM"; // 使用数据转换组件
            case "file":
                return "file";
            case "timer":
                return "DELAY"; // 使用延时组件
            case "delay":
                return "DELAY"; // 使用延时组件
            case "switch":
                return "switch";
            case "parallel":
                return "parallel";
            case "messagequeue":
                return "messagequeue";
            default:
                // 如果没有特殊映射，直接返回原节点类型
                return nodeType;
        }
    }

    /**
     * 生成节点组件映射（内部方法）
     */
    private Map<String, LiteFlowConvertResult.NodeComponentInfo> generateNodeComponentMappingInternal(
            List<LogicFlowData.Node> nodes) {

        Map<String, LiteFlowConvertResult.NodeComponentInfo> mapping = new HashMap<>();

        for (LogicFlowData.Node node : nodes) {
            // 跳过开始和结束节点
            if ("start".equals(node.getType().toLowerCase()) || "end".equals(node.getType().toLowerCase())) {
                continue;
            }

            LiteFlowConvertResult.NodeComponentInfo componentInfo = new LiteFlowConvertResult.NodeComponentInfo();
            componentInfo.setNodeId(node.getId());
            componentInfo.setNodeType(node.getType());
            componentInfo.setComponentName(getComponentName(node));
            componentInfo.setComponentClass(generateComponentClassName(node.getType()));
            componentInfo.setNodeConfig(node.getProperties());
            componentInfo.setNeedCreateComponent(true);

            mapping.put(node.getId(), componentInfo);
        }

        return mapping;
    }

    /**
     * 生成组件类名
     */
    private String generateComponentClassName(String nodeType) {
        switch (nodeType) {
            case "http":
                return "com.xp.flow.component.HttpRequestComponent";
            case "script":
                return "com.xp.flow.component.ScriptExecuteComponent";
            case "condition":
                return "com.xp.flow.component.ConditionComponent";
            case "transform":
                return "com.xp.flow.component.DataTransformComponent";
            case "timer":
                return "com.xp.flow.component.DelayComponent";
            case "delay":
                return "com.xp.flow.component.DelayComponent";
            case "email":
                return "com.xp.flow.component.EmailComponent";
            case "database":
                return "com.xp.flow.component.DatabaseComponent";
            case "file":
                return "com.xp.flow.component.FileComponent";
            case "parallel":
                return "com.xp.flow.component.ParallelComponent";
            case "loop":
                return "com.xp.flow.component.LoopComponent";
            default:
                return "com.xp.flow.component.HttpRequestComponent"; // 默认使用HTTP请求组件
        }
    }
}
